<!--
 * @Description: 流程分类树组件
 * @Author: DHL
 * @Date: 2022-03-28 14:25:56
 * @LastEditors: DHL
 * @LastEditTime: 2023-02-15 09:59:37
-->
<template>
  <div class="flow-category-tree-wrapper" v-loading="loading">
    <div class="tree-key-word">
      <el-input v-model="treeKeyWord" size="small" clearable placeholder="请输入关键字" />
    </div>
    <div class="toolbar">
      <el-button-group>
        <el-button size="small" @click="handleExpandTree(true)">展开</el-button>
        <el-button size="small" @click="handleExpandTree(false)">折叠</el-button>
        <el-button size="small" @click="handleSearchTree(true)">刷新</el-button>
      </el-button-group>
    </div>
    <div class="tree-content">
      <el-scrollbar height="100%">
        <el-tree
          ref="treeRef"
          node-key="id"
          :data="treeData"
          :props="treeProps"
          empty-text="暂无数据"
          :draggable="props.draggable"
          :default-expanded-keys="defaultExpandedKeys"
          :default-checked-keys="defaultExpandedKeys"
          show-checkbox
          check-strictly
          check-on-click-node
          highlight-current
          :expand-on-click-node="false"
          :filter-node-method="handleFilterTree"
          @node-drop="handleNodeDrop"
          @check="handleChecked"
        >
        </el-tree>
      </el-scrollbar>
    </div>
  </div>
</template>

<script lang="ts">
  export default { name: 'OrganizationTree' }
</script>

<script setup lang="ts">
  import { nextTick, onMounted, ref, watch } from 'vue'
  import { getTreeParentName } from '@/utils/treeUtils'
  import type Node from 'element-plus/es/components/tree/src/model/node'
  import type { DragEvents } from 'element-plus/es/components/tree/src/model/useDragNode'
  import { stringUtils } from '@/utils/stringUtils'
  import { ElMessage } from 'element-plus'
  import { FlowCategoryModel } from '@/api/flow/model/flowCategoryModel'
  import { apiFlowCategorySearchTree, apiFlowCategoryUpdateById } from '@/api/flow/flowCategory'

  // 采用ts专有声明，有默认值
  interface Props {
    draggable?: boolean
  }

  const props = withDefaults(defineProps<Props>(), {
    draggable: false
  })

  const emit = defineEmits(['nodeClick', 'search'])

  //////////////////////////////////////////////////
  // 属性
  //////////////////////////////////////////////////

  const loading = ref(false)

  const treeRef = ref()

  const treeData = ref()

  const listData = ref([] as Array<FlowCategoryModel>)

  const selectTreeNode = ref()

  const defaultExpandedKeys = ref()

  const treeProps = {
    label: 'name',
    children: 'children',
    disabled: 'false'
  }

  const treeKeyWord = ref()

  //////////////////////////////////////////////////
  // 函数
  //////////////////////////////////////////////////

  watch(treeKeyWord, (val: string) => {
    treeRef.value!.filter(val)
  })

  function handleFilterTree(value: string, data: any) {
    if (!value) return true
    return data.name.includes(value)
  }

  /**
   * tree查询
   */
  function handleSearchTree(reset = false) {
    if (reset) {
      handleChecked({} as Node)
    }

    apiFlowCategorySearchTree({}).then((result) => {
      treeData.value = result.treeData
      listData.value = result.listData

      if (selectTreeNode.value) {
        defaultExpandedKeys.value = [selectTreeNode.value.id]
      }
    })
  }

  /**
   * tree展开折叠
   */
  function handleExpandTree(isExpand: boolean) {
    treeRef.value.store._getAllNodes().forEach((item: { expanded: boolean }) => {
      item.expanded = isExpand
    })
  }

  /**
   * tree节点拖拽事件
   */
  function handleNodeDrop(draggingNode: Node, dropNode: Node, dropType: any, ev: DragEvents) {
    let pid = ''
    if ('inner' === dropType) {
      pid = dropNode.data.id
    } else {
      pid = dropNode.data.parentOrgId
    }

    if (stringUtils.isEmpty(pid)) {
      return
    }

    let nodeData: FlowCategoryModel = draggingNode.data as FlowCategoryModel
    nodeData.pid = pid

    apiFlowCategoryUpdateById(nodeData).then((result) => {
      if (result?.success) {
        ElMessage.success(result.message)
      } else {
        ElMessage.error(result?.message)
      }
    })
  }

  /**
   * 获取选中节点的父级名称集合
   */
  function getSelectNodeParentName() {
    const parentNames = getTreeParentName(
      listData.value,
      'id',
      'parentOrgId',
      'name',
      selectTreeNode.value
    )
    return parentNames
  }

  /**
   * 获取节点的父级名称集合
   * @param orgId
   */
  function getParentName(orgId: string) {
    const orgs = listData.value.filter((item) => {
      return item.id === orgId
    })
    const parentNames = getTreeParentName(listData.value, 'id', 'parentOrgId', 'name', orgs[0])
    return parentNames
  }

  /**
   * 切换选中状态
   */
  function handleChecked(treeNode: Node) {
    treeRef.value.setCheckedKeys([treeNode.id])
    selectTreeNode.value = treeNode
    emit('nodeClick', treeNode)
  }

  /**
   * 设置选中节点并展开
   * @param keys
   */
  function setChecked(keys: Array<string>) {
    if (keys && keys.length > 0) {
      nextTick(() => {
        treeRef.value.setCheckedKeys(keys)
        defaultExpandedKeys.value = keys
      })
    }
  }

  //////////////////////////////////////////////////
  // 生命周期
  //////////////////////////////////////////////////
  onMounted(() => {
    nextTick(() => {
      handleSearchTree()
    })
  })

  defineExpose({ getSelectNodeParentName, getParentName, handleSearchTree, setChecked })
</script>

<style scoped lang="scss">
  .flow-category-tree-wrapper {
    height: 100%;
    background-color: #ffffff;

    .splitpanes__pane {
      background-color: #ffffff;
    }

    .tree-key-word {
      padding: 0px 0px 5px 0px;
    }
    .toolbar {
      padding-right: 0px;
      text-align: right;
    }
    .tree-content {
      margin-top: 5px;
      height: calc(100% - 60px);
    }
  }
</style>
